package com.bestcem.xm.common.core.uitls;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 公共工具类 最后更新时间: 2021年6月4日15:05:55
 *
 * @author liheng
 * @version v1.0
 * @date 2021/5/13 15:56
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class CommonUtil {
    /**
     * java 时间存入 mongo 时间统一偏移量
     */
    public static final String INSERT_TIME_OFFSET = "+8";

    /**
     * id的String list转为ObjectId list
     *
     * @param ids String类型ids
     * @return ObjectId类型ids
     */
    public static List<ObjectId> stringToObjectId(List<String> ids) {
        List<ObjectId> objectIds = new ArrayList<>(ids.size());
        for (String id : ids) {
            objectIds.add(new ObjectId(id));
        }
        return objectIds;
    }

    /**
     * 获取uuid字符串，作为OSS中存储的文件名使用
     *
     * @return 例如:e08f4cfb4c0a4b7d8beaa7fb2cb08cf5
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 获取uuid字符串，作为OSS中存储的文件名使用
     *
     * @param ids ObjectId类型ids
     * @return String类型ids
     */
    public static List<String> objectIdToString(List<ObjectId> ids) {
        List<String> stringIds = new ArrayList<>(ids.size());
        for (ObjectId id : ids) {
            stringIds.add(id.toString());
        }
        return stringIds;
    }

    /**
     * 时间转为字符串 。 格式为“yyyy-MM-dd HH:mm:ss”
     *
     * @param dateTime
     * @return String
     * @author jy.zhao
     * @date 2021/5/19 11:35
     * @deprecated 对应方法见 {@link DateUtil#formatString(LocalDateTime)}
     */
    @Deprecated
    public static String timeToString(LocalDateTime dateTime) {
        return LocalDateTimeUtil.format(dateTime, DatePattern.NORM_DATETIME_PATTERN);
    }

    /**
     * 字符串转为时间。
     *
     * @param dateTime 格式为 yyyy-MM-dd HH:mm:ss
     * @return LocalDateTime
     * @author jy.zhao
     * @date 2021/5/20 14:08
     * @deprecated 对应方法见 {@link DateUtil#getLocalDateTime(String)}
     */
    @Deprecated
    public static LocalDateTime toLocalDateTime(String dateTime) {
        return LocalDateTimeUtil.parse(dateTime, DatePattern.NORM_DATETIME_PATTERN);
    }

    private static final Pattern IPV4_PATTERN = Pattern
            .compile("((\\d|[1-9]\\d|1\\d\\d|2([0-4]\\d|5[0-5]))\\.){3}(\\d|[1-9]\\d|1\\d\\d|2([0-4]\\d|5[0-5])){1,3}");

    /**
     * 获取ipv4 地址
     */
    public static String getIpv4(String ipStr) {
        if (StringUtils.isBlank(ipStr)) {
            return null;
        }
        Matcher matcher = IPV4_PATTERN.matcher(ipStr);
        if (matcher.find()) {
            return matcher.group(0);
        }
        return null;
    }

    /**
     * 获取当前时间 +8 小时的 Date
     *
     * @return Date of current time +8 hours
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/29 10:34
     * @deprecated 对应方法见 {@link DateUtil#getMongoDate()}
     */
    @Deprecated
    public static Date getPlusEightTime() {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.now().plusHours(Long.parseLong(INSERT_TIME_OFFSET));
        ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
        return Date.from(zonedDateTime.toInstant());
    }

    public static JSONObject formatAddressJsonObject(JSONArray addressJsonArray) {
        JSONObject addressMap = new JSONObject();
        if (addressJsonArray == null || addressJsonArray.isEmpty()) {
            return addressMap;
        }
        for (int i = 0; i < addressJsonArray.size(); i++) {
            JSONObject jsonObject = addressJsonArray.getJSONObject(i);
            String name = jsonObject.getString("name");
            JSONObject subAddress = formatAddressJsonObject(jsonObject.getJSONArray("sub"));
            addressMap.put(name, subAddress);
        }
        return addressMap;
    }

    /*public static Map<String, Map> formatAddressMap(JSONArray addressJsonArray) throws Exception {
        Map<String, Map> addressMap = new HashMap<>();
        if (addressJsonArray == null || addressJsonArray.isEmpty()) {
            return addressMap;
        }
        for (Object item : addressJsonArray) {
            JSONObject jsonObject = (JSONObject) item;
            Object name = jsonObject.get("name");
            Map<String, Map> subAddressMap = formatAddressMap((JSONArray) jsonObject.get("sub"));
            addressMap.put(name.toString(), subAddressMap);
        }
        return addressMap;
    }*/

    /**
     * Computes key.hashCode() and spreads (XORs) higher bits of hash
     * to lower.  Because the table uses power-of-two masking, sets of
     * hashes that vary only in bits above the current mask will
     * always collide. (Among known examples are sets of Float keys
     * holding consecutive whole numbers in small tables.)  So we
     * apply a transform that spreads the impact of higher bits
     * downward. There is a tradeoff between speed, utility, and
     * quality of bit-spreading. Because many common sets of hashes
     * are already reasonably distributed (so don't benefit from
     * spreading), and because we use trees to handle large sets of
     * collisions in bins, we just XOR some shifted bits in the
     * cheapest possible way to reduce systematic lossage, as well as
     * to incorporate impact of the highest bits that would otherwise
     * never be used in index calculations because of table bounds.
     */
    public static int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    /**
     * http https 字符串验证
     */
    public static String URL_REGEX = "^(https?://)?([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?$";

}
